package de.umr.fb12.vs.os;

import java.util.LinkedList;
import java.util.List;

/**
 * 
 * Task is the entity which is executed by the CPU and scheduled by the
 * Scheduler Classes via the Core Scheduler.
 * 
 * 
 */
public final class Task {
	/**
	 * 
	 * The enum States represents the states of a task.
	 * 
	 */
	public static enum STATES {
		DEAD, RUNNABLE, RUNNING, BLOCKED
	}

	static List<Task> task_list = new LinkedList<Task>();
	static int PIDS = 0;

	String name;
	SchedClass sched_class;
	Syscall.TYPES syscall;
	Object syscall_data;
	long usr = 0, sys = 0, iow = 0;
	int pid = 0, prio = 0, nice = 0;
	boolean need_resched = false;
	boolean idle_task = false;

	STATES state;

	CPU cpu;
	int[] reg; // register set
	int[] mem; // memory
	int ip; // instruction pointer

	Task(CPU cpu) {
		reg = new int[CPU.REG_COUNT];
		mem = new int[CPU.MEM_SIZE];
		state = STATES.BLOCKED;
		pid = PIDS++;
		this.cpu = cpu;
		synchronized (task_list) {
			task_list.add(this);
		}
	}

	void switch_to() {
		cpu.assign(this);
	}

	void loadProgram(int[] code) {
		ip = 0;
		System.arraycopy(code, 0, mem, 0, code.length);
		state = STATES.RUNNABLE;
	}

	/**
	 * Sets need_resched to true. Schedule will ask the schedulers for a new
	 * task.
	 */
	public void set_tsk_need_resched() {
		need_resched = true;
	}

	/**
	 * Sets need_resched to false. Schedule wont pick a new Task if the currents
	 * task need_resched flag is set to flase.
	 */
	public void clear_tsk_need_resched() {
		need_resched = false;
	}

	/**
	 * Queries for the value of need_resched.
	 * 
	 * @return need_resched flag
	 */
	public boolean need_resched() {
		return need_resched;
	}

	/**
	 * Returns the state of this task.
	 * 
	 * @return Task.STATE
	 */
	public STATES getState() {
		return state;
	}

	/**
	 * Returns the priority of this task.
	 * 
	 * @return long priority
	 */
	public long getPrio() {
		return prio;
	}

	/**
	 * Returns the scheduler class which schedules this task.
	 * 
	 * @return refernece to the Schedclass
	 */
	public SchedClass getSchedclass() {
		return sched_class;
	}

	/**
	 * Queries the time this task spend in "user-mode"
	 * 
	 * @return long nanoseconds
	 */
	public long getUsr() {
		return usr;
	}

	/**
	 * Queries the time this task spend waiting for I/O.
	 * 
	 * @return long nanoseconds
	 */
	public long getIow() {
		return iow;
	}

	/**
	 * Queries the process id of this task.
	 * 
	 * @return int process id
	 */
	public int getPid() {
		return pid;
	}

	/**
	 * Queries the nice value of this task.
	 * 
	 * @return int nanoseconds
	 */
	public int getNice() {
		return nice;
	}

	/**
	 * Checks if this tas is a idle task.
	 * 
	 * @return true if this task is a/the idle task
	 */
	public boolean isIdle_task() {
		return idle_task;
	}

	/**
	 * Queries the time this task spend in "sys-mode" handling IRQs/syscalls.
	 * 
	 * @return long nanoseconds
	 */
	public long getSys() {
		return sys;
	}

}